<html>

<style>
    * {
        margin: 0;
    }

    #content {
        color: white;
        position: absolute;
        left: -20px;
        top: -10px;
        white-space: pre-wrap;
        height: 200px;
        overflow: auto;
    }
</style>

<script type="importmap">
	{
	  "imports": {
		"three": "../../../three.js-r151/build/three.module.js",
		"three/addons/": "../../../three.js-r151/examples/jsm/"
	  }
	}
</script>

<body>
    <div id="content">
        1. sprite和mesh一样近小远大，但是它只能是一个始终平行于屏幕的平面
        2. 精灵模型对象Sprite和网格模型对象mesh的创建一样需要材质，而且只能是SpriteMaterial，但是sprite不需要Geometry。
    </div>
    <div id="canvas"></div>

    <script type="module">
        import * as THREE from 'three';
        import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

        // 1. 必须创建的三大件
        // 1.1 三维场景Scene, 类似创建了个世界，三维世界
        const scene = new THREE.Scene();
        const geometry = new THREE.BoxGeometry(1, 1, 1);
        const material = new THREE.MeshBasicMaterial({ color: 'yellow' });
        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);

        // 添加辅助坐标系
        const axesHelper = new THREE.AxesHelper(5);
        scene.add(axesHelper);

        // 1.2 相机
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight,
            5, 100);
        camera.position.set(12, 12, 12)

        // 1.3 渲染器
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        let canvasDom = document.getElementById("canvas");
        canvasDom.appendChild(renderer.domElement);


        // 2. 设置相机控件轨道控制器OrbitControls
        new OrbitControls(camera, canvasDom);

        // 3. 精灵模型  rain snow  MeshBasicMaterial  SpriteMaterial
        const texture = new THREE.TextureLoader().load("./rain.png");
        const spriteMaterial = new THREE.SpriteMaterial({
            map: texture,
            transparent: true,
            opacity: 0.7,
            color: 'white',
            side: THREE.DoubleSide,
        });


        // 雨滴在3D空间随机分布
        const group = new THREE.Group();
        for (let i = 0; i < 100; i++) {
            // 精灵模型共享材质
            const sprite = new THREE.Sprite(spriteMaterial);

            // sprite.rotation.x = -Math.PI / 2;
            // sprite.rotation.x = Math.PI * Math.random();

            group.add(sprite);
            sprite.scale.set(1, 1, 1);
            // 设置精灵模型位置，在长方体空间上上随机分布
            const x = 30 * (Math.random() - 0.5);
            const y = 15 * Math.random();
            const z = 30 * (Math.random() - 0.5);
            sprite.position.set(x, y, z)
        }
        scene.add(group)


        // 匀速落下
        const clock = new THREE.Clock();
        function render(param) {
            renderer.render(scene, camera);
            requestAnimationFrame(render)

            // loop()两次执行时间间隔
            const t = clock.getDelta();
            console.log("t", t, param);

            // loop()每次执行都会更新雨滴的位置，进而产生动画效果
            group.children.forEach(sprite => {
                // 雨滴的y坐标每次减1
                // sprite.position.y -= 0.15;
                // sprite.position.y -= 0.03 * (15.006 - sprite.position.y);
                let y = sprite.position.y;
                let a = 0.03;
                sprite.position.y -= 0.5 * (Math.sqrt(30 * a - 2 * a * y) + a)

                if (sprite.position.y < 0) {
                    // 如果雨滴落到地面，重置y，从新下落
                    sprite.position.y = 15;
                }
            });
        }
        render();



    </script>
</body>

</html>